/** 
 * History:
 * 2017年5月23日下午2:06:56 彭明华创建
 */  
package com.shockweb.common.serializable.json;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.shockweb.common.International;
import com.shockweb.common.serializable.SerializableObject;
import com.shockweb.common.utils.ClassUtil;
import com.shockweb.common.utils.classmethod.ClassMethod;
import com.shockweb.common.utils.classmethod.ClassMethodDefine;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
/**
 * Json解析类能将json字符串，生成Pojo实例
 * @author: 彭明华
 * History:
 * 2017年5月23日  彭明华创建
 *
 */
public class JsonReader
{

	
	/**
	 * 构造方法
	 */
    public JsonReader() {}


    /**
     * 从jsonStr字符串中读取，并构造成rootClass的实例返回，rootClass[0]为根对象，后面为根对象的内部对象，如List的内部对象
     * @param jsonStr json字符串
     * @param rootClass 多个Class定义,如：classDefines是rootClass中set方法中List的对象描述
     * @return Object 返回实例
     * @throws JsonException
     */
	public Object readString(String jsonStr, Class<?>... rootClass) throws JsonException
	{
		if(jsonStr==null || "".equals(jsonStr.trim())){
			return null;
		}
		Object rtn = null;
        try
        {
    		if(List.class.isAssignableFrom(rootClass[0])){
       			rtn = readListValue(JSONArray.parseArray(jsonStr), rootClass[0],rootClass, null,0,"list",0);
    		}else if(Map.class.isAssignableFrom(rootClass[0])){
    			rtn = readMapValue(JSONObject.parseObject(jsonStr), rootClass[0], rootClass,null,0,"map",0);
    		}else if(isCustomClass(rootClass[0])){
    			rtn = readValue(JSONObject.parseObject(jsonStr), rootClass[0],rootClass, null);
    		}else{
   				rtn = convertValue(rootClass[0],getValue(JSONObject.parseObject(jsonStr), "value"));
    		}
        }
        catch(Throwable e)
        {
            throw new JsonException(e);
        }
        return rtn;
    }
	

    /**
     * 将value转化成cls的实例
     * @param cls 类定义
     * @param value 原数据
     * @return Object 实例
     * @throws ParseException
     */
    private Object convertValue(Class<?> cls, String value) throws ParseException
    {
    	if(value!=null){
            if(String.class.equals(cls)){
            	return value.replaceAll("\"\"", "\"");
            }
            if(StringBuffer.class.equals(cls)){
            	return new StringBuffer(value.replaceAll("\"\"", "\""));
            }
            if(StringBuilder.class.equals(cls)){
            	return new StringBuilder(value.replaceAll("\"\"", "\""));
            }
            if(BigDecimal.class.equals(cls)){
    			try{
    				return new BigDecimal(value);
    			}catch(Exception e){
    				return new BigDecimal(value.replaceAll(",",""));
    			}
            }if(double.class.equals(cls) || Double.class.equals(cls)){
    			DecimalFormat decParser = new DecimalFormat(International.IN_DECIMAL);
    			return decParser.parse(value).doubleValue();
            }if(float.class.equals(cls) || Float.class.equals(cls)){
    			DecimalFormat decParser = new DecimalFormat(International.IN_DECIMAL);
    			return decParser.parse(value).floatValue();
            }if(int.class.equals(cls) || Integer.class.equals(cls)){
    			DecimalFormat decParser = new DecimalFormat(International.IN_INTEGER);
    			return decParser.parse(value).intValue();
            }if(long.class.equals(cls) || Long.class.equals(cls)){
    			DecimalFormat decParser = new DecimalFormat(International.IN_INTEGER);
    			return decParser.parse(value).longValue();
            }if(short.class.equals(cls) || Short.class.equals(cls)){
    			DecimalFormat decParser = new DecimalFormat(International.IN_INTEGER);
    			return decParser.parse(value).shortValue();
            }if(byte.class.equals(cls) || Byte.class.equals(cls))
                return new Byte(value);
            if(char.class.equals(cls) || Character.class.equals(cls))
                return value.charAt(0);
            if(Date.class.equals(cls))
            {
                SimpleDateFormat sdf = new SimpleDateFormat(International.IN_DATETIME);
                return new Date(sdf.parse(value).getTime());
            }
            if(Time.class.equals(cls))
            {
                SimpleDateFormat sdf = new SimpleDateFormat(International.IN_TIME);
                return new Time(sdf.parse(value).getTime());
            }
            if(Timestamp.class.equals(cls))
            {
                SimpleDateFormat sdf = new SimpleDateFormat(International.IN_DATETIMEMSEL);
                return new Timestamp(sdf.parse(value).getTime());
            }
            if(java.util.Date.class.equals(cls))
            {
                SimpleDateFormat sdf = new SimpleDateFormat(International.IN_DATETIME);
                return sdf.parse(value);
            }
            if(boolean.class.equals(cls) || Boolean.class.equals(cls))
                return new Boolean(value);
            if(byte[].class.equals(cls) || byte[].class.equals(cls))
                return SerializableObject.base64Decode(value);
            if(BigInteger.class.equals(cls)){
    			try{
    				return new BigInteger(value);
    			}catch(Exception e){
    				return new BigInteger(value.replaceAll(",",""));
    			}
            }
    	}
        return null;
    }

    /**
     * 判断是否用户自定义类
     * @param cls 类定义
     * @return boolean 如果是自定义类返回true，否则返回false
     */
    public static boolean isCustomClass(Class<?> cls){
        if(String.class.equals(cls))
            return false;
        if(StringBuffer.class.equals(cls))
            return false;
        if(BigDecimal.class.equals(cls))
            return false;
        if(double.class.equals(cls) || Double.class.equals(cls))
            return false;
        if(float.class.equals(cls) || Float.class.equals(cls))
            return false;
        if(int.class.equals(cls) || Integer.class.equals(cls))
            return false;
        if(long.class.equals(cls) || Long.class.equals(cls))
            return false;
        if(short.class.equals(cls) || Short.class.equals(cls))
            return false;
        if(boolean.class.equals(cls) || Boolean.class.equals(cls))
            return false;
        if(byte.class.equals(cls) || Byte.class.equals(cls))
            return false;
        if(char.class.equals(cls) || Character.class.equals(cls))
            return false;
        if(Date.class.equals(cls))
            return false;
        if(Time.class.equals(cls))
            return false;
        if(Timestamp.class.equals(cls))
            return false;
        if(java.util.Date.class.equals(cls))
            return false;
        if(boolean.class.equals(cls) || Boolean.class.equals(cls))
            return false;
        if(BigInteger.class.equals(cls))
            return false;
        if(StringBuilder.class.equals(cls))
            return false;
        if(byte[].class.equals(cls))
            return false;
        return true;
    }
    
    
    /**
     * 获取JSONObject的name的数据
     * @param object JSONObject元素或对象
     * @param name 查询的对象
     * @return String
     */
    public String getValue(Object object,String name){
    	if(object==null){
    		return null;
    	}
    	if(object instanceof JSONObject){
    		return ((JSONObject)object).getString(name);
    	}else{
    		return object.toString();
    	}
    }

    
    /**
     * 读取一个jsonObject
     * @param jsonObject JSONObject元素
     * @param classDefine class定义
     * @param rootClassDefine 多个rootClassDefine
     * @param method 方法定义
     * @return Object 返回实例
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws IllegalArgumentException
     * @throws InvocationTargetException
     * @throws ClassNotFoundException
     * @throws ParseException
     */
    private Object readValue(JSONObject jsonObject, Class<?> classDefine,Class<?>[] rootClassDefine,Method method)
        throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException, ParseException
    {
        Object rtn = null;
        if(classDefine == null)
            return null;
        if(jsonObject != null){
        	try{
        		if(classDefine.isInterface()){
        			Class<?> newClass = ClassUtil.getClassDefine(method,rootClassDefine,0);
        			if(newClass==null){
        				return null;
        			}
        			rtn = newClass.newInstance();
        		}else{
        			if(classDefine.equals(Object.class)){
        				Class<?> newClass = ClassUtil.getClassDefine(method,rootClassDefine,0);
            			if(newClass!=null){
            				rtn = newClass;
            			}
        			}else{
        				rtn = classDefine.newInstance();
        			}
        		}
        	}catch(InstantiationException e){
        		throw new InstantiationException(classDefine.getName() + e.getMessage());
        	}catch(IllegalAccessException e2){
        		throw new IllegalAccessException(classDefine.getName() + e2.getMessage());
        	}catch(IllegalArgumentException e3){
        		throw new IllegalArgumentException(classDefine.getName(),e3);
        	}
    		if(isCustomClass(classDefine)){
	        	List<ClassMethodDefine> methods = ClassMethod.getSetMethods(rtn.getClass());
	            for(ClassMethodDefine setMethod : methods)
	            {
	                Method m = setMethod.getMethod();
	                Object value = null;
	                boolean flag = true;
	                if(jsonObject.get(setMethod.getName())==null){
	                	m.invoke(rtn, new Object[]{null});
	                }else{
		                if(List.class.isAssignableFrom(m.getParameterTypes()[0])){
		                	value = readListValue(jsonObject.getJSONArray(setMethod.getName()), m.getParameterTypes()[0],rootClassDefine, setMethod.getMethod(),0,setMethod.getName(),0);
		                }else if(Map.class.isAssignableFrom(m.getParameterTypes()[0])){
		                	value = readMapValue(jsonObject.getJSONObject(setMethod.getName()), m.getParameterTypes()[0],rootClassDefine, setMethod.getMethod(),0,setMethod.getName(),0);
		                }else{
		                    if(isCustomClass(m.getParameterTypes()[0])){
	                    		value = readValue(jsonObject.getJSONObject(setMethod.getName()), m.getParameterTypes()[0],rootClassDefine,setMethod.getMethod());
		                    }else{
		                    	String tValue = getValue(jsonObject, setMethod.getName());
		                    	if(tValue == null){
		                    		flag = false;
		                    	}else{
		                    		value = convertValue(m.getParameterTypes()[0],tValue);
		                    	}
		                    }
		                }
		                if(flag){
		                	m.invoke(rtn, new Object[]{value});
		                }else{
		                	return null;
		                }
	                }
	            }
        	}else{
            	rtn = convertValue(classDefine,getValue(jsonObject, "value"));
        	}
        }
        return rtn;
    }
    
    /**
     * 读取list中的值
     * @param jsonArray DJSONArray元素
     * @param classDefine class定义
     * @param rootClassDefine 多个rootClassDefine
     * @param method 方法定义
     * @param index class的索引
     * @param name Element的名称
     * @param valueIndex 读取值的索引
     * @return Object 返回实例
     * @throws IllegalArgumentException
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws ClassNotFoundException
     * @throws ParseException
     */
	@SuppressWarnings("unchecked")
	private List<Object> readListValue(JSONArray jsonArray, Class<?> classDefine,Class<?>[] rootClassDefine,Method method,int index,String name,int valueIndex)
        throws IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException, ClassNotFoundException, ParseException
    {
        List<Object> list = null;

        if(classDefine.isInterface()){
        	Class<?> newClass = ClassUtil.getClassDefine(method,rootClassDefine,index);
			if(newClass!=null && !newClass.isInterface() && List.class.isAssignableFrom(newClass)){
				list = (List<Object>)newClass.newInstance();
			}else {
				list = new ArrayList<Object>();
			}
        }else{
        	List<Object> newInstance = (List<Object>)classDefine.newInstance();
			list = newInstance;
        }
        if(classDefine!=null || method != null){
        	Class<?> newClass = ClassUtil.getClassDefine(method,rootClassDefine,index+1);
			if(newClass==null){
				return null;
			}else{
                if(List.class.isAssignableFrom(newClass)){
                	for(int i=0;i<jsonArray.size();i++){
                		Object value = readListValue(jsonArray.getJSONArray(i), newClass,rootClassDefine, method,index+1,name,i);
                		list.add(value);
                	}
                }else if(Map.class.isAssignableFrom(newClass)){
                	for(int i=0;i<jsonArray.size();i++){
                		Object value = readMapValue(jsonArray.getJSONObject(i), newClass, rootClassDefine,method,index+1,name,i);
                		list.add(value);
                	}
                }else if(isCustomClass(newClass)){
                	for(int i=0;i<jsonArray.size();i++){
                		Object value = readValue(jsonArray.getJSONObject(i), newClass,rootClassDefine,method);
                		list.add(value);
                	}
	        	}else{
                	for(int i=0;i<jsonArray.size();i++){
        				Object value = convertValue(newClass,getValue(jsonArray.get(i),"value"));
        				list.add(value);
                	}
	            }
        	}
        }
        return list;
    }
	
    /**
     * 读取list中的值
     * @param jsonObject JSONObject元素
     * @param classDefine class定义
     * @param rootClassDefine 多个rootClassDefine
     * @param method 方法定义
     * @param indexElement的名称
     * @param name Element的名称
     * @param valueIndex读取值的索引
     * @return Object 返回实例
     * @throws IllegalArgumentException
     * @throws InstantiationException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws ClassNotFoundException
     * @throws ParseException
     */
	@SuppressWarnings("unchecked")
	private Map<Object,Object> readMapValue(JSONObject jsonObject, Class<?> classDefine,Class<?>[] rootClassDefine,Method method,int index,String name,int valueIndex)
        throws IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException, ClassNotFoundException, ParseException
    {
		Map<Object,Object> map = null;
        if(classDefine.isInterface()){
        	Class<?> newClass = ClassUtil.getClassDefine(method,rootClassDefine,index);
			if(newClass!=null && !newClass.isInterface() && Map.class.isAssignableFrom(newClass)){
				map = (Map<Object,Object>)newClass.newInstance();
			}else {
				map = new HashMap<Object,Object>();
			}
        }else{
        	Map<Object,Object> newInstance = (Map<Object,Object>)classDefine.newInstance();
        	map = newInstance;
        }
        if(classDefine!=null || method != null){
        	Class<?> keyClass = ClassUtil.getClassDefine(method,rootClassDefine,index+1);
        	Class<?> valueClass = ClassUtil.getClassDefine(method,rootClassDefine,index+2);
			if(keyClass==null || valueClass==null || jsonObject==null){
				return null;
			}else{
				Iterator<?> iterator = jsonObject.keySet().iterator();
				while(iterator.hasNext()){
					Object key = iterator.next();
					if(key!=null){
						Object v = jsonObject.get(key);
						if(v==null){
							map.put(convertValue(keyClass,key.toString()),null);
						}else{
							if(List.class.isAssignableFrom(valueClass)){
								JSONArray value = (JSONArray)v;
								map.put(convertValue(keyClass,key.toString()),readListValue(value, valueClass,rootClassDefine, method,index+2,key.toString(),0));
							}else if(Map.class.isAssignableFrom(valueClass)){
								JSONObject value = (JSONObject)v;
								map.put(convertValue(keyClass,key.toString()),readMapValue(value, valueClass,rootClassDefine, method,index+2,key.toString(),0));
							}else if(isCustomClass(valueClass)){
								JSONObject value = (JSONObject)v;
								map.put(convertValue(keyClass,key.toString()),readValue(value,valueClass,rootClassDefine,method));
							}else{
								String value = v.toString();
								map.put(convertValue(keyClass,key.toString()),convertValue(keyClass,value));
							}
						}
					}
				}
			}
        }
        return map;
    }
    

}